Popular Searches
Popular Course Categories
Popular Courses

Using StringBuilder and StringBuffer

Using StringBuilder and StringBuffer

Strings and String Manipulation

Using StringBuilder and StringBuffer in Java

Course: Core Java Training

Topic: Using StringBuilder and StringBuffer

Course Link: Core Java Training Course

Demo Link: Register for a Free Course Demo

Academy Website: JustAcademy


1. Introduction to StringBuilder and StringBuffer

In Java, strings are represented by the String class. A String object is immutable, which means its contents cannot be changed after the object is created. Whenever a program modifies a String, Java creates a new String object for the resulting value.

Repeatedly creating new String objects can cause unnecessary object creation when a program performs many concatenation or modification operations. Java provides the StringBuilder and StringBuffer classes to work with mutable sequences of characters.

Both classes allow developers to append, insert, delete, replace, and reverse characters without creating a new object for every modification.

Learning Objectives

  • Understand mutable character sequences in Java.
  • Learn the purpose of StringBuilder and StringBuffer.
  • Compare String, StringBuilder, and StringBuffer.
  • Use common methods such as append(), insert(), delete(), replace(), and reverse().
  • Understand thread safety and synchronization.
  • Choose the appropriate class for different programming situations.

2. What Is StringBuilder?

StringBuilder is a Java class used to create and modify a mutable sequence of characters. It is useful when a program needs to construct or change text repeatedly.

StringBuilder is not synchronized. Its methods do not provide built-in synchronization for safe concurrent modification by multiple threads. This generally makes it a suitable choice for local text manipulation performed by a single thread.

Syntax

StringBuilder builder = new StringBuilder();
StringBuilder builderWithText = new StringBuilder("Hello");

Example

public class StringBuilderExample {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("Hello");
        builder.append(" Java");
        System.out.println(builder);
    }
}

Output:

Hello Java

The append() method adds text to the existing character sequence. The builder itself is modified, and the returned reference points to the same StringBuilder object.

3. What Is StringBuffer?

StringBuffer is another Java class for creating and modifying a mutable sequence of characters. Its methods are synchronized, which helps coordinate access to individual operations when the same StringBuffer instance is shared by multiple threads.

StringBuffer can be useful when multiple threads need to work with the same mutable text object. However, synchronization of individual methods does not automatically make a sequence of several operations atomic. Additional synchronization or another coordination mechanism may be necessary when a complete multi-step operation must be performed as one unit.

Syntax

StringBuffer buffer = new StringBuffer();
StringBuffer bufferWithText = new StringBuffer("Hello");

Example

public class StringBufferExample {
    public static void main(String[] args) {
        StringBuffer buffer = new StringBuffer("Hello");
        buffer.append(" Java");
        System.out.println(buffer);
    }
}

Output:

Hello Java

Like StringBuilder, StringBuffer supports common text modification operations. The main distinction is that StringBuffer synchronizes its methods, while StringBuilder does not.

4. Understanding Mutable and Immutable Strings

Immutable String

String text = "Java";
text.concat(" Programming");
System.out.println(text);

Output:

Java

The concat() method returns a new String. Since the returned value is not assigned back to text, the original variable still refers to "Java".

Mutable StringBuilder

StringBuilder text = new StringBuilder("Java");
text.append(" Programming");
System.out.println(text);

Output:

Java Programming

The StringBuilder object's contents are changed by the append operation.

Mutable StringBuffer

StringBuffer text = new StringBuffer("Java");
text.append(" Programming");
System.out.println(text);

Output:

Java Programming

StringBuffer also changes its existing character sequence through the append operation.

5. Difference Between String, StringBuilder, and StringBuffer

Feature String StringBuilder StringBuffer
Mutability Immutable Mutable Mutable
Modification Produces a new String when content changes Modifies its character sequence Modifies its character sequence
Synchronization Immutable content; no synchronization needed for its contents Methods are not synchronized Methods are synchronized
Typical use Fixed text and string values Repeated text changes in a single-threaded context Shared mutable text when synchronized methods are useful
Performance considerations Repeated concatenation can create extra objects Often preferred for repeated modifications without synchronization Synchronization may add overhead
Common methods concat(), substring(), equals() append(), insert(), delete(), reverse() append(), insert(), delete(), reverse()

StringBuilder is not guaranteed to outperform StringBuffer in every situation. Actual performance depends on the workload, Java version, and how the code is used. Prefer the class that fits the program's correctness and concurrency requirements.

6. Creating StringBuilder and StringBuffer Objects

Using the Default Constructor

StringBuilder sb = new StringBuilder();
StringBuffer sf = new StringBuffer();

Both objects begin with an empty character sequence and can grow as text is appended. Their default initial capacity is 16 characters.

Using a String Argument

StringBuilder sb = new StringBuilder("Core Java");
StringBuffer sf = new StringBuffer("Core Java");

The supplied text becomes the initial content of the object. The initial capacity is the length of that text plus 16.

Using a Capacity Argument

StringBuilder sb = new StringBuilder(50);
StringBuffer sf = new StringBuffer(50);

The capacity indicates how much character storage is initially available before the internal storage needs to grow. Capacity is not the same as the current length.

7. The append() Method

The append() method adds a value to the end of the existing character sequence. It supports strings, characters, numbers, booleans, character arrays, and other supported types.

Example

public class AppendExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Java");
        sb.append(" Programming");
        sb.append(" ");
        sb.append(2026);

        System.out.println(sb);
    }
}

Output:

Java Programming 2026

Appending Different Data Types

StringBuilder sb = new StringBuilder();
sb.append("Age: ");
sb.append(25);
sb.append(", Active: ");
sb.append(true);

System.out.println(sb);

Output:

Age: 25, Active: true

Practical use: append() is commonly used to construct messages, logs, SQL text, reports, and formatted output. When building SQL queries, use prepared statements and parameters for user-supplied values rather than concatenating untrusted input.

8. The insert() Method

The insert() method inserts a value at a specified position in the existing sequence. Characters at and after that position shift to the right.

Syntax

builder.insert(index, value);

Example

public class InsertExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello Java");
        sb.insert(6, "Core ");

        System.out.println(sb);
    }
}

Output:

Hello Core Java

The index must be between zero and the current length, inclusive. An invalid index causes an IndexOutOfBoundsException.

9. The replace() Method

The replace() method replaces characters between a starting index and an ending index. The start index is inclusive, while the end index is exclusive.

Example

public class ReplaceExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("I like Python");
        sb.replace(7, 13, "Java");

        System.out.println(sb);
    }
}

Output:

I like Java

Here, the characters at positions 7 through 12 are replaced with "Java". This method replaces a range by index; it is not the same as globally searching for a matching word.

10. The delete() and deleteCharAt() Methods

The delete() method removes a range of characters. The deleteCharAt() method removes one character at a specified index.

Using delete()

StringBuilder sb = new StringBuilder("Hello World");
sb.delete(5, 11);
System.out.println(sb);

Output:

Hello

Using deleteCharAt()

StringBuilder sb = new StringBuilder("Java!");
sb.deleteCharAt(4);
System.out.println(sb);

Output:

Java

Check the indexes before removing characters. An invalid index or range can cause an IndexOutOfBoundsException.

11. The reverse() Method

The reverse() method reverses the order of characters in the current sequence. It is available in both StringBuilder and StringBuffer.

Example

public class ReverseExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Java");
        sb.reverse();

        System.out.println(sb);
    }
}

Output:

avaJ

Checking a Palindrome

public class PalindromeExample {
    public static void main(String[] args) {
        String word = "madam";
        String reversed = new StringBuilder(word).reverse().toString();

        if (word.equals(reversed)) {
            System.out.println("Palindrome");
        } else {
            System.out.println("Not a palindrome");
        }
    }
}

Output:

Palindrome

This example compares the original String with a reversed String. For case-insensitive or punctuation-insensitive palindrome checking, normalize the input before comparing.

12. Other Useful StringBuilder and StringBuffer Methods

Method Purpose Example
length() Returns the number of characters currently in the sequence. sb.length()
capacity() Returns the current storage capacity. sb.capacity()
charAt(index) Returns the character at a specified index. sb.charAt(0)
setCharAt(index, ch) Changes the character at a specified index. sb.setCharAt(0, 'J')
substring(start) Returns a String containing characters from the specified start index to the end. sb.substring(5)
substring(start, end) Returns a String for the specified range, with the end index excluded. sb.substring(0, 4)
indexOf(text) Finds the first occurrence of a string. sb.indexOf("Java")
setLength(length) Changes the sequence length, truncating or adding null characters as needed. sb.setLength(4)
ensureCapacity(minimum) Requests sufficient capacity for a specified minimum. sb.ensureCapacity(100)
toString() Creates a String representation of the current sequence. sb.toString()
trimToSize() Attempts to reduce capacity to match the current length. sb.trimToSize()

13. Understanding length() and capacity()

The length() method returns how many characters are currently stored. The capacity() method returns how many characters can fit in the current internal storage before it needs to grow.

Example

public class CapacityExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Java");

        System.out.println("Length: " + sb.length());
        System.out.println("Capacity: " + sb.capacity());
    }
}

Output:

Length: 4
Capacity: 20

The initial capacity is 16 plus the length of the supplied string, so the capacity is 20 in this example. If more characters are appended than the available capacity can hold, the internal storage grows automatically.

14. Converting StringBuilder or StringBuffer to String

Methods that expect a String may require conversion from a StringBuilder or StringBuffer. Use toString() to obtain a String containing the current characters.

Example

public class ConversionExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Core Java");
        String text = sb.toString();

        System.out.println(text);
        System.out.println(text.getClass().getSimpleName());
    }
}

Output:

Core Java
String

The returned String is immutable. Changing the StringBuilder afterward does not change the String value that was already created.

15. StringBuilder and StringBuffer in Multithreaded Programs

Thread safety matters when multiple threads access the same mutable object. StringBuilder does not synchronize its methods, so concurrent modifications to one shared instance can interfere with one another. StringBuffer synchronizes its individual methods, providing more protection for shared access.

Choosing the Appropriate Class

  • Use StringBuilder for local operations in a single thread or when external synchronization safely manages access.
  • Consider StringBuffer when multiple threads share one mutable character sequence and synchronized methods suit the design.
  • Remember that separate StringBuilder instances can safely be used independently by different threads.
  • Do not assume that calling several synchronized StringBuffer methods makes the entire sequence of calls atomic.

Example of a Shared StringBuffer

public class SharedBufferExample {
    public static void main(String[] args) throws InterruptedException {
        StringBuffer buffer = new StringBuffer();

        Thread first = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                buffer.append("A");
            }
        });

        Thread second = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                buffer.append("B");
            }
        });

        first.start();
        second.start();

        first.join();
        second.join();

        System.out.println(buffer.length());
    }
}

Possible output:

200

In this example, each append call is synchronized by StringBuffer. The order of A and B characters can vary. The example assumes the threads only append and that no other code modifies the buffer concurrently.

16. Performance Considerations

StringBuilder is often a good choice for repeatedly constructing text in a single thread because its methods do not incur StringBuffer's built-in synchronization. StringBuffer may be useful when synchronized methods are appropriate for shared mutable state.

Repeated concatenation of immutable Strings in a loop can create many intermediate objects. A builder often reduces that object creation by modifying one character sequence repeatedly. However, Java compilers and runtimes can optimize some concatenation expressions, so the actual difference depends on the code and runtime.

Example: Repeated Concatenation

String result = "";
for (int i = 0; i < 5; i++) {
    result += i;
}
System.out.println(result);

Output:

01234

Using StringBuilder

StringBuilder result = new StringBuilder();
for (int i = 0; i < 5; i++) {
    result.append(i);
}
System.out.println(result);

Output:

01234

For large or repeated text-building operations, StringBuilder is commonly preferred. For very small expressions, ordinary concatenation can be perfectly readable and efficient. Benchmark realistic workloads before making performance claims.

17. Practical Example: Building a Student Report

The following program demonstrates how StringBuilder can combine multiple values into a readable report.

public class StudentReport {
    public static void main(String[] args) {
        StringBuilder report = new StringBuilder();

        report.append("Student Report\n");
        report.append("------------------\n");
        report.append("Name: Riya\n");
        report.append("Course: Core Java\n");
        report.append("Score: ");
        report.append(92);
        report.append("%\n");
        report.append("Status: Passed");

        System.out.println(report.toString());
    }
}

Output:

Student Report
------------------
Name: Riya
Course: Core Java
Score: 92%
Status: Passed

This approach is useful for generating reports, receipts, summaries, logs, and other text that is built from multiple values.

18. Common Mistakes and Troubleshooting

Mistake Explanation Solution
Using == to compare content == compares object references, not character content. Use toString().equals(otherString) when comparing with a String.
Confusing length and capacity Length counts current characters; capacity describes available internal storage. Use length() for content size and capacity() for storage capacity.
Using invalid indexes Some methods throw IndexOutOfBoundsException for invalid positions. Check the current length and method's index rules.
Assuming StringBuilder is thread-safe Its methods are not synchronized. Use appropriate synchronization or choose a suitable concurrency design.
Assuming StringBuffer makes every workflow atomic Individual synchronized method calls do not automatically protect a multi-step operation as one unit. Synchronize the whole operation when required.
Forgetting to call toString() A method may require a String rather than a mutable builder. Use builder.toString() where a String is required.
Overusing mutable builders Simple concatenation may be clearer for a short expression. Choose the simplest approach that fits the workload.

19. Best Practices

  • Prefer StringBuilder for repeated text modifications in ordinary single-threaded code.
  • Use StringBuffer only when its synchronized operations fit the application's shared-state requirements.
  • Choose a reasonable initial capacity when the expected output size is known and large enough to matter.
  • Use meaningful variable names such as messageBuilder or reportBuffer.
  • Use toString() when a String result is required.
  • Check indexes and ranges carefully when using insert(), delete(), and replace().
  • Do not rely on synchronization alone to solve every concurrency problem; protect compound operations where necessary.
  • Use prepared statements for database parameters instead of assembling SQL from untrusted input.
  • Prefer clear, maintainable code over premature micro-optimization.

20. Practice Exercises

  1. Create a StringBuilder object containing your name and append your course name.
  2. Write a program that inserts the word "Core" into the text "Java Training".
  3. Replace "Python" with "Java" in a StringBuilder object.
  4. Remove all characters after a given index using delete().
  5. Reverse a word and check whether it is a palindrome.
  6. Build a shopping receipt containing product names, quantities, and prices.
  7. Print the length and capacity of a StringBuilder before and after appending text.
  8. Write a short program that demonstrates converting a StringBuilder into a String.
  9. Compare the intended uses of String, StringBuilder, and StringBuffer in a short explanation.
  10. Create a multithreaded example that shares a StringBuffer and prints its final length.

21. Interview Questions and Answers

Q1. What is StringBuilder in Java?

StringBuilder is a mutable sequence of characters that supports repeated text modifications without requiring a new object for every operation.

Q2. What is StringBuffer?

StringBuffer is a mutable sequence of characters whose methods are synchronized.

Q3. What is the main difference between StringBuilder and StringBuffer?

StringBuilder methods are not synchronized, while StringBuffer methods are synchronized. This affects their suitability for shared mutable state and may affect performance.

Q4. Why is StringBuilder commonly used in loops?

It allows the program to append text to a mutable character sequence rather than repeatedly producing new intermediate String values.

Q5. Are StringBuilder and StringBuffer immutable?

No. Both are mutable, so operations can change their character sequences.

Q6. What does append() do?

It adds a value to the end of the existing character sequence.

Q7. What is the difference between length() and capacity()?

length() returns the number of current characters. capacity() returns the available internal storage capacity before the sequence needs to grow.

Q8. What does reverse() do?

It reverses the order of characters in the sequence.

Q9. How can a StringBuilder be converted to a String?

Call its toString() method.

Q10. Is StringBuffer always the best choice for multithreaded applications?

No. It synchronizes individual methods, but the overall design still needs correct coordination for compound operations. Other approaches may be more suitable depending on the application.

Q11. Can StringBuilder be used safely by multiple threads?

Independent StringBuilder instances can be used by separate threads. Concurrently modifying the same instance without coordination is unsafe.

Q12. What happens if an invalid index is passed to insert() or deleteCharAt()?

These methods can throw an IndexOutOfBoundsException.

22. Quick Revision

  • String: immutable sequence of characters.
  • StringBuilder: mutable and not synchronized; commonly used for repeated text changes in single-threaded code.
  • StringBuffer: mutable and synchronizes its methods.
  • append(): adds content at the end.
  • insert(): adds content at a specified position.
  • replace(): replaces a range of characters.
  • delete(): removes a range of characters.
  • deleteCharAt(): removes one character.
  • reverse(): reverses the sequence.
  • length(): returns the number of current characters.
  • capacity(): returns the current storage capacity.
  • toString(): returns a String representation of the current contents.

23. Conclusion

StringBuilder and StringBuffer are essential Java classes for working with mutable text. Both provide methods for appending, inserting, replacing, deleting, and reversing characters. StringBuilder is generally a convenient choice for repeated text construction when a shared synchronized object is not needed, while StringBuffer offers synchronized methods for certain shared-state scenarios.

Understanding their mutability, method behavior, capacity, and thread-safety differences helps developers write clearer and more efficient Java programs. Practice the examples and exercises to become comfortable using both classes in real-world applications.

24. Further Learning Resources

whatsapp